/*
 * @Author: xiguan
 * @Email: xiguan.teng@qq.com
 * @Version: 1.0
 * @Date: 2022-07-11 18:00:10
 * @LastEditTime: 2022-07-31 15:49:39
 */



#ifndef _ALLOCMY_H_
#define _ALLOCMY_H_

#include <cstdlib>

namespace MySTL{

    /**
     * @brief : 空间配置器， 以字节为单位分配。 内部使用
     */    
    class alloc{

    private:
        enum EAlign{ ALIGN = 8 }; // 小型区块的上调边界
        enum EMaxBytes{ MAXBYTES = 128 }; // 小型区块的上限，超过的区块由 malloc 分配
        enum ENFreeLists{ NFREELISTS = ( EMaxBytes::MAXBYTES / EAlign::ALIGN ) }; // free-lists 的个数
        enum ENObjs{ NOBJS = 20 }; // 每次增加的节点数
    
    private:
        /**
         * @brief : free-lists 的节点构造
         */    
        union obj
        {
            union obj *next;
            char client[1];
        };
        
        static obj *free_list[ENFreeLists::NFREELISTS];

    private:
        static char *start_free; // 内存池起始位置
        static char *end_free; // 内存池结束位置
        static size_t heap_size;

    public:
        static void *allocate( size_t bytes );
        static void deallocate( void *ptr, size_t bytes );
        static void *reallocate( void *ptr, size_t old_sz, size_t new_sz );

    private:
		
        /**
         * @brief : 将 bytes 上调至8的倍数
         * @return size_t
         * @param {size_t} bytes
         */        
		static size_t ROUND_UP( size_t bytes ){
			return ( ( bytes + EAlign::ALIGN - 1 ) & ~( EAlign::ALIGN - 1 ) );
		}
        /**
         * @brief : 根据区块大小，决定使用第 n 号 free-list ，n 从0开始计算
         * @return size_t
         * @param {size_t} bytes
         */		 
		static size_t FREELIST_INDEX( size_t bytes ){
			return ( ( ( bytes ) + EAlign::ALIGN - 1 ) / EAlign::ALIGN - 1 );
		}
        /**
         * @brief : 返回一个大小为 n 的对象，并可能加入大小为 n 的其他区块到 free-list
         * @return void *
         * @param {size_t} bytes
         */        
        static void *refill( size_t bytes );
        /**
         * @brief : 配置一大块空间，可容纳 nobjs 个大小为 size 的区块。 如果配置 nobjs 个区块有所不便，nobjs 可能会降低
         * @return char *
         * @param {size_t} bytes
         * @param {size_t} &nobjs
         */        
        static char *chunk_alloc( size_t bytes, size_t &nobjs );

    };
    
}



#endif